package zhihuilan.common.utils;

import cn.binarywang.wx.miniapp.api.WxMaService;
import com.alibaba.fastjson.JSONObject;
import com.huaban.analysis.jieba.JiebaSegmenter;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.html2pdf.HtmlConverter;
import me.chanjar.weixin.common.error.WxErrorException;
import net.sourceforge.pinyin4j.PinyinHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import zhihuilan.entity.tools.ToolsLocation;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.SecureRandom;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class ToolsUtils {


    public static List<String> jiebaUtils(String args) {
        JiebaSegmenter js = new JiebaSegmenter();
        List<String> resultList = js.sentenceProcess(args); //[我, 爱, 中国]
        return resultList;
    }


    public static Boolean isMobile(String mobile) {
        String PHONE_REGEX = "^1[3-9]\\d{9}$";
        Pattern PHONE_PATTERN = Pattern.compile(PHONE_REGEX);
        if (mobile == null) {
            return false;
        }
        // 使用正则表达式进行匹配
        return PHONE_PATTERN.matcher(mobile).matches();
    }

    /**
     * 中国正常GCJ02坐标---->百度地图BD09坐标
     * 腾讯地图用的也是GCJ02坐标
     *
     * @param lat 纬度
     * @param lng 经度
     */
    public static Map qq2baidu(Double lat, Double lng) {
        Double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
        Double x = lng;
        Double y = lat;
        Double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
        Double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
        lng = z * Math.cos(theta) + 0.0065;
        lat = z * Math.sin(theta) + 0.006;
        Map map = new HashMap();
        map.put("lng", lng);
        map.put("lat", lat);
        return map;
    }

    /**
     * 百度地图BD09坐标---->中国正常GCJ02坐标
     * 腾讯地图用的也是GCJ02坐标
     *
     * @param lat 纬度
     * @param lng 经度
     * @return array();
     */
    public static Map baidu2qq(Double lat, Double lng) {
        Double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
        Double x = lng - 0.0065;
        Double y = lat - 0.006;
        Double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
        Double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
        lng = z * Math.cos(theta);
        lat = z * Math.sin(theta);
        Map map = new HashMap();
        map.put("lng", lng);
        map.put("lat", lat);
        return map;
    }

    /**
     * 百度地图BD09坐标---->中国正常GCJ02坐标
     * 腾讯地图用的也是GCJ02坐标
     *
     * @param latStr 经纬度
     * @param lngStr 经纬度
     * @return array();
     */
    public static ToolsLocation qq2baidu(String latStr, String lngStr) {
        ToolsLocation location = new ToolsLocation();
        location.setLng("");
        location.setLat("");
        if (ObjectUtils.isEmpty(latStr) || ObjectUtils.isEmpty(lngStr)) {
            return location;
        }
        Double lng = Double.parseDouble(lngStr);
        Double lat = Double.parseDouble(latStr);
        Double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
        Double x = lng;
        Double y = lat;
        Double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
        Double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
        lng = z * Math.cos(theta) + 0.0065;
        lat = z * Math.sin(theta) + 0.006;
        location.setLng(lng + "");
        location.setLat(lat + "");
        return location;
    }

    /**
     * 百度地图BD09坐标---->中国正常GCJ02坐标
     * 腾讯地图用的也是GCJ02坐标
     *
     * @param latStr 经纬度
     * @param lngStr 经纬度
     * @return array();
     */
    public static ToolsLocation baidu2qq(String latStr, String lngStr) {
        ToolsLocation location = new ToolsLocation();
        location.setLng("");
        location.setLat("");
        if (ObjectUtils.isEmpty(latStr) || ObjectUtils.isEmpty(lngStr)) {
            return location;
        }
        Double lng = Double.parseDouble(latStr);
        Double lat = Double.parseDouble(latStr);
        Double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
        Double x = lng - 0.0065;
        Double y = lat - 0.006;
        Double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
        Double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
        lng = z * Math.cos(theta);
        lat = z * Math.sin(theta);
        location.setLat(lat + "");
        location.setLng(lng + "");
        return location;
    }

    private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);

    /**
     * 小程序验证文字数据是否合规
     *
     * @param {String} msg 内容
     * @param {String} openid 微信openid
     */
    public static String verifymsg(String msg, String openid, WxMaService wxMaService) throws WxErrorException, UnknownHostException {
        String host = InetAddress.getLocalHost().getHostName();
        System.out.println(host);
        if (host.equals("wwww.huafeixianlan.com") || host.equals("www.zhihuilan.cn")) {
            String accessToken = wxMaService.getAccessToken();
            String url = "https://api.weixin.qq.com/wxa/msg_sec_check?access_token=" + accessToken;
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("content", msg);
            jsonObject.put("openid", openid);
            jsonObject.put("scene", 2);
            jsonObject.put("version", 2);
            String result = HttpUtils.sendPost(url, jsonObject.toJSONString());
            return result;
        } else {
            return "{\"result\":{\"suggest\":\"pass\"}}";
        }
    }

    /**
     * 小程序验证图片、视频数据是否合规
     *
     * @param {string} media_url 数据url
     * @param {string} openid 微信openid
     * @param {string} media_type  数据类型
     */
    public static String verifymedia(String media_url, String openid, String media_type, WxMaService wxMaService) throws UnknownHostException, WxErrorException {
        String host = InetAddress.getLocalHost().getHostName();
        if (host.equals("wwww.huafeixianlan.com") || host.equals("www.zhihuilan.cn")) {
            String accessToken = wxMaService.getAccessToken();
            String url = "https://api.weixin.qq.com/wxa/media_check_async?access_token=" + accessToken;
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("media_url", media_url);
            jsonObject.put("media_type", media_type);
            jsonObject.put("openid", openid);
            jsonObject.put("scene", 1);
            jsonObject.put("version", 2);
            String result = HttpUtils.sendPost(url, jsonObject.toJSONString());
            return result;
        } else {
            return "{\"trace_id\":\"321321\"}";
        }
    }

    /**
     * 根据前端传过来值获取ip
     *
     * @param {HttpServletRequest} httpServletRequest 前端传过来的值
     */
    public static String getIP() {
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        return request.getRemoteAddr();
    }

    public static String randomStr(Integer length) {
        String characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
        Random random = new Random();
        StringBuilder password = new StringBuilder();
        for (int i = 0; i < length; i++) {
            int index = random.nextInt(characters.length());
            password.append(characters.charAt(index));
        }
        return password.toString();
    }


    /**
     * sql计算距离公式
     *
     * @param lng
     * @param lat
     */
    public static String getDistanceSql(String lat, String lng) {
        return "( 6378.137 * 2 * asin(sqrt(pow(sin((latgd * pi() / 180 - " + lat + " * pi() / 180) / 2),2) + cos(latgd * pi() / 180) * cos(" + lat + " * pi() / 180) * pow(sin((lnggd * pi() / 180 - " + lng + " * pi() / 180) / 2),2))))*1000 ";

    }


    /**
     * 获取当天0点时间戳
     */
    public static Long getTodayZeroTime() {
        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime().getTime();
    }

    /**
     * 将字符串中带'＊', '*', 'x', 'X', '×', '✘'的字符全部替换成×；
     *
     * @return 返回替换完成之后的字符串；
     */
    public static String replaceCharToSearch(String boforeString) {
        String result = boforeString.replace('＊', '×').replace('*', '×').replace('x', '×').replace('X', '×').replace('×', '×').replace('✘', '×');
        return result;
    }

    /**
     * 将字符串中带'＊', '*', 'x', 'X', 'X', '✘'的字符全部替换成X；
     *
     * @return 返回替换完成之后的字符串；
     */
    public static String replaceCharToSearch1(String boforeString) {
        String result = boforeString.replace('＊', 'X').replace('*', 'X').replace('x', 'X').replace('×', 'X').replace('✘', 'X');
        return result;
    }

    /**
     * 腾讯地图坐标定位封装计算距离sql；（适用于mysql）
     *
     * @param lng
     * @param lat
     */
    public static String getDistanceSqlTencent(String lat, String lng) {
        return " (6371 * acos( " +
                " cos(radians(lat)) * cos(radians(" + lat + ")) * " +
                " cos(radians(lng) - radians(" + lng + ")) +  " +
                " sin(radians(lat)) * sin(radians(" + lat + ")) " +
                " )) ";

    }

    public static double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
        double EARTH_RADIUS = 6371.0;
        // 将经纬度转换为弧度
        double lat1Rad = Math.toRadians(lat1);
        double lon1Rad = Math.toRadians(lon1);
        double lat2Rad = Math.toRadians(lat2);
        double lon2Rad = Math.toRadians(lon2);

        // 计算纬度和经度的差值
        double deltaLat = lat2Rad - lat1Rad;
        double deltaLon = lon2Rad - lon1Rad;

        // 应用 Haversine 公式
        double a = Math.pow(Math.sin(deltaLat / 2), 2) +
                Math.cos(lat1Rad) * Math.cos(lat2Rad) *
                        Math.pow(Math.sin(deltaLon / 2), 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

        // 计算距离
        return EARTH_RADIUS * c*1000;
    }

    /**
     * 字符串表情验证；是否存在表情；
     *
     * @return 是否存在表情；
     */
    public static boolean containsEmoji(String string) {
        // 匹配所有基本的表情符号范围
        String regEx = "[\\ud800\\udc00-\\udbff\\udfff\\ud800-\\udfff]";
        Pattern pattern = Pattern.compile(regEx);
        Matcher matcher = pattern.matcher(string);
        return matcher.find();
    }

    /**
     * 去除首尾字符串中包含的字符串；注意，这里会先去掉首尾空格；
     */
    public static String trimLeftAndRight(String value, String replace) {
        if (ObjectUtils.isEmpty(value)) {
            return null;
        }
        return value.replaceAll("^,+", "").replaceAll(",+$", "");
    }

    /**
     * 获取字符串第一个字符转拼音的首字母大写；
     */
    public static String getFirstLetterUpper(String chinese) {
        if (chinese == null || chinese.isEmpty()) {
            return "";
        }
        if (chinese.matches("^[\\u4e00-\\u9fa5].*")) {
            String pinyin = PinyinHelper.toHanyuPinyinStringArray(chinese.charAt(0))[0]; // 获取拼音数组，取第一个字符的拼音
            if (pinyin != null && pinyin.length() > 0) {
                return pinyin.substring(0, 1).toUpperCase(); // 获取拼音的首字母并大写
            }
        }
        return ""; // 非汉字字符的处理
    }

    /**
     * Java 反射机制可以在运行时获取类的信息，包括字段名和字段值。我们可以利用反射机制将实体类的字段名和值转成Map
     * */
    public static Map<String, Object> toMap(Object entity) throws IllegalAccessException {
        Map<String, Object> map = new HashMap<>();
        Class<?> cls = entity.getClass();
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            String fieldName = field.getName();
            Object fieldValue = field.get(entity);
            map.put(fieldName, fieldValue);
        }
        return map;
    }
    private static final char[] HEX_ARRAY = "0123456789abcdef".toCharArray();
    /**
     * 仿PHP   bin2hex() 函数（将二进制数据转换为十六进制字符串）
     * */
    public static String bin2hexFast(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for (int i = 0; i < bytes.length; i++) {
            int v = bytes[i] & 0xFF;
            hexChars[i * 2] = HEX_ARRAY[v >>> 4]; // 高4位
            hexChars[i * 2 + 1] = HEX_ARRAY[v & 0x0F]; // 低4位
        }
        return new String(hexChars);
    }

    /**
     * 仿PHP PHP 的 random_bytes(5) 函数（生成加密安全的随机字节）
     * 生成指定长度的随机字节数组
     *
     */
    public static byte[] randomBytes(int length) {
        SecureRandom secureRandom = new SecureRandom();
        byte[] bytes = new byte[length];
        secureRandom.nextBytes(bytes);
        return bytes;
    }

    /**
     * 四舍五入double类型值；
     * */
    public static double to_price(double value){
        String formattedNumber = String.format("%.2f", value);
        Double val = Double.parseDouble(formattedNumber);
        return (double) Math.round(val * 100) / 100.0;
    }

    public static String createPdf(){
        String htmlContent = "<h1>Hello, World!</h1><p>This is a paragraph.</p>";
        String dest = "output.pdf"; // 输出PDF文件的路径
        try (PdfWriter writer = new PdfWriter(dest);
             PdfDocument pdf = new PdfDocument(writer)) {
            HtmlConverter.convertToPdf(htmlContent,writer);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //TODO
        return "";
    }

}
